package graphic;

import java.util.ArrayList;
import objects.Triangle;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import klient.Klient;
import objects.Ngbh;
import objects.VectorAvg;
import objects.VinT;
import openGL11.Engine;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.vector.Vector3f;
import org.newdawn.slick.opengl.Texture;

/**
 *  
 * @author Marcin & Bartek
 * 
 * @description not used
 */
public class Terrain {
    List<Triangle> list = new ArrayList<>();
    List<Triangle> llist = new LinkedList<>();
    int ID;
    float res;
    float x;
    float y;
    int tX=0;
    int tY=0;
    Texture tex;
    Texture tex2;
    
    public void draw(){
        Graphic.e.drawList(ID);
    }
    
    public void compile(){
        boolean road=false;
        ID=Graphic.e.createList();
        
        Graphic.e.startList(ID);
        {
            Graphic.e.setColor(new Color(1,1,1,1));
            Graphic.e.bind(tex);
            Graphic.e.startDrawT();
            for(Triangle t:llist){
                if(t.type==1&& !road){
                    Graphic.e.endDraw();
                    Graphic.e.bind(tex2);
                    Graphic.e.startDrawT();
                    road=true;
                }else if(t.type==0 && road){
                    Graphic.e.endDraw();
                    Graphic.e.bind(tex);
                    Graphic.e.startDrawT();
                    road=false;
                }
                Graphic.e.drawTNwT(t);
                               
            }
            Graphic.e.endDraw();
            Graphic.e.unbind();
        }
        Graphic.e.endList();
        
    }
    
    public boolean ledge(int nr){
        if(nr%2==1)nr--;
        if((nr+2)%(tY*2)==0) return true;
        return false;
    }
    public boolean redge(int nr){
        if(nr%2==1)nr--;
        if((nr)%(tY*2)==0) return true;
        return false;
    }
    
    public void setVert0(int nr,float x, float y, float z,int wc){
        if(nr<0||nr>=list.size()) return;
        if((wc&1) == 1)list.get(nr).x[0]=x;
        if((wc&2) == 2)list.get(nr).y[0]=y;
        if((wc&4) == 4)list.get(nr).z[0]=z;
    }
    public void setVert1(int nr,float x, float y, float z,int wc){
        if(nr<0||nr>=list.size()) return;
        if((wc&1) == 1) list.get(nr).x[1]=x;
        if((wc&2) == 2) list.get(nr).y[1]=y;
        if((wc&4) == 4) list.get(nr).z[1]=z;
    }
    public void setVert2(int nr,float x, float y, float z,int wc){
        if(nr<0||nr>=list.size()) return;
        if((wc&1) == 1) list.get(nr).x[2]=x;
        if((wc&2) == 2) list.get(nr).y[2]=y;
        if((wc&4) == 4) list.get(nr).z[2]=z;
    }
    public void setVert0wl(int nr,float x, float y, float z,int wc){
        if(ledge(nr)) return;
        if(nr<0||nr>=list.size()) return;
        if((wc&1) == 1)list.get(nr).x[0]=x;
        if((wc&2) == 2)list.get(nr).y[0]=y;
        if((wc&4) == 4)list.get(nr).z[0]=z;
    }
    public void setVert1wl(int nr,float x, float y, float z,int wc){
        if(ledge(nr)) return;
        if(nr<0||nr>=list.size()) return;
        if((wc&1) == 1) list.get(nr).x[1]=x;
        if((wc&2) == 2) list.get(nr).y[1]=y;
        if((wc&4) == 4) list.get(nr).z[1]=z;
    }
    public void setVert2wl(int nr,float x, float y, float z,int wc){
        if(ledge(nr)) return;
        if(nr<0||nr>=list.size()) return;
        if((wc&1) == 1) list.get(nr).x[2]=x;
        if((wc&2) == 2) list.get(nr).y[2]=y;
        if((wc&4) == 4) list.get(nr).z[2]=z;
    }
    public void setVert0wr(int nr,float x, float y, float z,int wc){
        if(redge(nr)) return;
        if(nr<0||nr>=list.size()) return;
        if((wc&1) == 1)list.get(nr).x[0]=x;
        if((wc&2) == 2)list.get(nr).y[0]=y;
        if((wc&4) == 4)list.get(nr).z[0]=z;
    }
    public void setVert1wr(int nr,float x, float y, float z,int wc){
        if(redge(nr)) return;
        if(nr<0||nr>=list.size()) return;
        if((wc&1) == 1) list.get(nr).x[1]=x;
        if((wc&2) == 2) list.get(nr).y[1]=y;
        if((wc&4) == 4) list.get(nr).z[1]=z;
    }
    public void setVert2wr(int nr,float x, float y, float z,int wc){
        if(redge(nr)) return;
        if(nr<0||nr>=list.size()) return;
        if((wc&1) == 1) list.get(nr).x[2]=x;
        if((wc&2) == 2) list.get(nr).y[2]=y;
        if((wc&4) == 4) list.get(nr).z[2]=z;
    }
    
    public void changeTriangleVert(int nr,int v,float x, float y, float z,int wc){
        int tY2=tY*2;
        if(nr%2==0){//dolny
            if(v==0){
                setVert0(nr,x,y,z,wc);
                setVert1(nr+1,x,y,z,wc);
                setVert0wl(nr-1,x,y,z,wc);
                setVert1(nr+tY2,x,y,z,wc);
                setVert2wl(nr+tY2-1,x,y,z,wc);
                setVert2wl(nr+tY2-2,x,y,z,wc);
            }else if(v==1){
                setVert1(nr,x,y,z,wc);
                setVert2wl(nr-1,x,y,z,wc);
                setVert2wl(nr-2,x,y,z,wc);
                setVert0(nr-tY2,x,y,z,wc);
                setVert0wl(nr-tY2-1,x,y,z,wc);
                setVert1(nr-tY2+1,x,y,z,wc);
            }else if(v==2){
                setVert2(nr,x,y,z,wc);
                setVert2(nr+1,x,y,z,wc);
                setVert1wr(nr+2,x,y,z,wc);
                setVert0(nr-tY2+1,x,y,z,wc);
                setVert0wr(nr-tY2+2,x,y,z,wc);
                setVert1wr(nr-tY2+3,x,y,z,wc);
            }
        }else{//górny
            if(v==0){
                setVert0(nr,x,y,z,wc);
                setVert0wr(nr+1,x,y,z,wc);
                setVert1wr(nr+2,x,y,z,wc);
                setVert2(nr+tY2,x,y,z,wc);
                setVert2(nr+tY2-1,x,y,z,wc);
                setVert1wr(nr+tY2+1,x,y,z,wc);
            }else if(v==1){
                setVert1(nr,x,y,z,wc);
                setVert0(nr-1,x,y,z,wc);
                setVert0wl(nr-2,x,y,z,wc);
                setVert1(nr+tY2-1,x,y,z,wc);
                setVert2wl(nr+tY2-2,x,y,z,wc);
                setVert2wl(nr+tY2-3,x,y,z,wc);
            }else if(v==2){
                setVert2(nr,x,y,z,wc);
                setVert1wr(nr+1,x,y,z,wc);
                setVert2(nr-1,x,y,z,wc);
                setVert0(nr-tY2,x,y,z,wc);
                setVert0wr(nr-tY2+1,x,y,z,wc);
                setVert1wr(nr-tY2+2,x,y,z,wc);
            }
        }
    }
    
    public Triangle getTriangle(float gx,float gy){
        gx+=x/2;
        gy+=y/2;
        if(gx<0||gy<0||gx>x||gy>y) return null;
        gx/=res;
        gy/=res;
        
        int c=(int)gx*tY+(int)gy;
        c*=2;
        if(1-(gx-(int)gx)<gy-(int)gy) ++c;
        if(c<0 || c>=list.size()) return null;
        return list.get(c);
    }
    
    public int getTriangleNr(float gx,float gy){
        gx+=x/2;
        gy+=y/2;
        if(gx<0||gy<0||gx>x||gy>y) return -1;
        
        gx/=res;
        gy/=res;
        
        int c=(int)gx*tY+(int)gy;
        c*=2;
        if(1-(gx-(int)gx)<gy-(int)gy) ++c;
        if(c<0 || c>=list.size()) return -1;
        return c;
    }
     public void gen2(float res,float x, float y){
        tex=TextureBase.get("images/GrassGreenTexture0004.png");
        tex2=TextureBase.get("images/cobble.png");
        GL11.glBindTexture(GL11.GL_TEXTURE_2D, 2);
        this.x=x;
        this.y=y;
        this.res=res;
        float hx=x/2;
        float hy=y/2;
        
        list.clear();
        Random r=new Random(System.nanoTime());
        tX=(int)(x/res);
        tY=(int)(y/res);
        float t[][][]=new float[tX+1][tY+1][4];
        
        for(float i=0;i<tX+1;i++){
            for(float j=0;j<tY+1;j++){
                
                t[(int)i][(int)j][0]=i*res;
                if((i>tX/2-WorldConfig.PATH_WIDTH&&i<tX/2+WorldConfig.PATH_WIDTH) || 
                   (j>tY/2-WorldConfig.PATH_WIDTH &&j<tY/2+WorldConfig.PATH_WIDTH)){
                    t[(int)i][(int)j][1]=0.f;
                    t[(int)i][(int)j][3]=1;
                }
                else{
                    t[(int)i][(int)j][1]=r.nextFloat()*0.6f;
                    t[(int)i][(int)j][3]=0;
                }
                t[(int)i][(int)j][2]=j*res;
            }
        }
        for(float i=0;i<tX;i++){
            for(float j=0;j<tY;j++){
                Triangle buf = new Triangle();
                buf.x[1]=t[(int)i][(int)j][0]-hx;
                buf.texx[1]=0f;
                buf.x[0]=t[(int)i+1][(int)j][0]-hx;
                buf.texx[0]=1f;
                buf.x[2]=t[(int)i][(int)j+1][0]-hx;
                buf.texx[2]=0f;
                buf.y[1]=t[(int)i][(int)j][1];
                buf.y[0]=t[(int)i+1][(int)j][1];
                buf.y[2]=t[(int)i][(int)j+1][1];
                buf.z[1]=t[(int)i][(int)j][2]-hy;
                buf.texz[1]=0f;
                buf.z[0]=t[(int)i+1][(int)j][2]-hy;
                buf.texz[0]=0f;
                buf.z[2]=t[(int)i][(int)j+1][2]-hy;
                buf.texz[2]=1f;
                if(t[(int)i][(int)j][3]+t[(int)i+1][(int)j][3]+t[(int)i][(int)j+1][3]==3){
                    buf.type=1;
                }
                buf.calcNormal();
                buf.number=list.size();
                list.add(buf);
                
                Triangle buf2 = new Triangle();
                buf2.x[0]=t[(int)i+1][(int)j+1][0]-hx;
                buf2.texx[0]=1f;
                buf2.x[1]=t[(int)i+1][(int)j][0]-hx;
                buf2.texx[1]=1f;
                buf2.x[2]=t[(int)i][(int)j+1][0]-hx;
                buf2.texx[2]=0f;
                buf2.y[0]=t[(int)i+1][(int)j+1][1];
                buf2.y[1]=t[(int)i+1][(int)j][1];
                buf2.y[2]=t[(int)i][(int)j+1][1];
                buf2.z[0]=t[(int)i+1][(int)j+1][2]-hy;
                buf2.texz[0]=1f;
                buf2.z[1]=t[(int)i+1][(int)j][2]-hy;
                buf2.texz[1]=0f;
                buf2.z[2]=t[(int)i][(int)j+1][2]-hy;
                buf2.texz[2]=1f;
                if(t[(int)i+1][(int)j+1][3]+t[(int)i+1][(int)j][3]+t[(int)i][(int)j+1][3]==3){
                    buf2.type=1;
                }
                buf2.calcNormal();
                buf2.number=list.size();
                list.add(buf2);
            }
        }
        
       doAvgNorm();
    }
    public void gen(float res,float x, float y){
        tex=TextureBase.get("images/GrassGreenTexture0004.png");
        tex2=TextureBase.get("images/cobble.png");
        GL11.glBindTexture(GL11.GL_TEXTURE_2D, 2);
        this.x=x;
        this.y=y;
        this.res=res;
        float hx=x/2;
        float hy=y/2;
        
        list.clear();
        Random r=new Random(System.nanoTime());
        tX=(int)(x/res);
        tY=(int)(y/res);
        float t[][][]=new float[tX+1][tY+1][4];
        
        for(float i=0;i<tX+1;i++){
            for(float j=0;j<tY+1;j++){
                
                t[(int)i][(int)j][0]=i*res;
                if((i>tX/2-WorldConfig.PATH_WIDTH&&i<tX/2+WorldConfig.PATH_WIDTH) || 
                   (j>tY/2-WorldConfig.PATH_WIDTH &&j<tY/2+WorldConfig.PATH_WIDTH)){
                    t[(int)i][(int)j][1]=0.f;
                    t[(int)i][(int)j][3]=1;
                }
                else{
                    t[(int)i][(int)j][1]=r.nextFloat()*0.6f;
                    t[(int)i][(int)j][3]=0;
                }
                t[(int)i][(int)j][2]=j*res;
            }
        }
        for(float i=0;i<tX;i++){
            for(float j=0;j<tY;j++){
                Triangle buf = new Triangle();
                buf.x[1]=t[(int)i][(int)j][0]-hx;
                buf.texx[1]=0f;
                buf.x[0]=t[(int)i+1][(int)j][0]-hx;
                buf.texx[0]=1f;
                buf.x[2]=t[(int)i][(int)j+1][0]-hx;
                buf.texx[2]=0f;
                buf.y[1]=t[(int)i][(int)j][1];
                buf.y[0]=t[(int)i+1][(int)j][1];
                buf.y[2]=t[(int)i][(int)j+1][1];
                buf.z[1]=t[(int)i][(int)j][2]-hy;
                buf.texz[1]=0f;
                buf.z[0]=t[(int)i+1][(int)j][2]-hy;
                buf.texz[0]=0f;
                buf.z[2]=t[(int)i][(int)j+1][2]-hy;
                buf.texz[2]=1f;
                if(t[(int)i][(int)j][3]+t[(int)i+1][(int)j][3]+t[(int)i][(int)j+1][3]==3){
                    buf.type=1;
                }
                buf.calcNormal();
                buf.number=list.size();
                list.add(buf);
                
                Triangle buf2 = new Triangle();
                buf2.x[0]=t[(int)i+1][(int)j+1][0]-hx;
                buf2.texx[0]=1f;
                buf2.x[1]=t[(int)i+1][(int)j][0]-hx;
                buf2.texx[1]=1f;
                buf2.x[2]=t[(int)i][(int)j+1][0]-hx;
                buf2.texx[2]=0f;
                buf2.y[0]=t[(int)i+1][(int)j+1][1];
                buf2.y[1]=t[(int)i+1][(int)j][1];
                buf2.y[2]=t[(int)i][(int)j+1][1];
                buf2.z[0]=t[(int)i+1][(int)j+1][2]-hy;
                buf2.texz[0]=1f;
                buf2.z[1]=t[(int)i+1][(int)j][2]-hy;
                buf2.texz[1]=0f;
                buf2.z[2]=t[(int)i][(int)j+1][2]-hy;
                buf2.texz[2]=1f;
                if(t[(int)i+1][(int)j+1][3]+t[(int)i+1][(int)j][3]+t[(int)i][(int)j+1][3]==3){
                    buf2.type=1;
                }
                buf2.calcNormal();
                buf2.number=list.size();
                list.add(buf2);
            }
        }
        
       doAvgNorm();
    }
    public void doAvgNorm(){
        Ngbh.Init(tY*2);
        int tY2=tY*2;
        Vector3f ret;
        VectorAvg avg = new VectorAvg();
        for(int i=0;i<list.size();i+=3){
            if((i/(tY2))%2==1 && i/(tY2)!=tX-1){
                i=((i/(tY2))+1)*(tY2);                
            }
            for(int j=0;j<3;++j){
                for(int k=0;k<6;++k){
                    if(Ngbh.get(i, j, k).Triangle+i<0 || Ngbh.get(i, j, k).Triangle+i>=list.size()) break;
                    avg.add(list.get(Ngbh.get(i, j, k).Triangle+i).normal[0], 
                            list.get(Ngbh.get(i, j, k).Triangle+i).normal[1], 
                            list.get(Ngbh.get(i, j, k).Triangle+i).normal[2]);
                }
                ret = avg.get();
                for(int k=0;k<6;++k){
                    if(Ngbh.get(i, j, k).Triangle+i<0 || Ngbh.get(i, j, k).Triangle+i>=list.size()) break;
                    list.get(Ngbh.get(i, j, k).Triangle+i).normalx[Ngbh.get(i, j, k).Vert]=ret.x;
                    list.get(Ngbh.get(i, j, k).Triangle+i).normaly[Ngbh.get(i, j, k).Vert]=ret.y;
                    list.get(Ngbh.get(i, j, k).Triangle+i).normalz[Ngbh.get(i, j, k).Vert]=ret.z;
                }
                avg.clear();
            }
        }
        for(Triangle t:list){            
            t.normalizeAll();
            llist.add(t);
        }
        Triangle w1 = new Triangle(-x*2,-0.01f,-y*2,-x*2,-0.01f,y*2,x*2,-0.01f,-y*2)
                ,w2 = new Triangle(x*2,-0.01f,-y*2,-x*2,-0.01f,y*2,x*2,-0.01f,y*2);
        w1.col=WorldConfig.TERRAIN_COLOR; w2.col=WorldConfig.TERRAIN_COLOR;
        w1.calcNormaln(); w2.calcNormaln();
        llist.add(w1);llist.add(w2);
        compile();
    }
}
